#pragma once

#include "defines.h"
#include "platform/vk/vk_device_context.h"

namespace vkrender
{
    struct SpriteVertex
    {
        glm::vec2 pos;
        glm::vec3 color;
        glm::vec2 texcoords;
        static std::vector<VkVertexInputBindingDescription> getBindingDescriptions();
        static std::vector<VkVertexInputAttributeDescription> getAttributeDescriptions();
    };

    struct Sprite2D
    {
        virtual uint32_t numVertices() const = 0;
        virtual uint32_t numIndices() const = 0;
        virtual void copyVertices() const = 0;
        virtual void copyIndices() const = 0;
    };

    struct SpriteQuad
    {
    public:
        glm::vec2 pos;
        glm::vec2 size;
        glm::vec3 color;

        SpriteQuad(const glm::vec2& pos, const glm::vec2& size, const glm::vec3& color)
        {
            this->pos = pos;
            this->size = size;
            this->color = color;
        }

        uint32_t num_vertices() const { return 4; }
        uint32_t num_indices() const { return 6; }
    };

    struct SpriteTriangle
    {

    };

    struct SpriteBuffer
    {
    private:
        std::shared_ptr<VulkanDeviceContext> context;
        VkDevice device;
        VkPhysicalDevice physicalDevice;
        VkBuffer vertexbuffer;
        VkDeviceMemory vertexmemory;
        VkBuffer indexbuffer;
        VkDeviceMemory indexmemory;

        uint32_t max_index_count;

        uint32_t vertex_count;
        uint32_t index_count;
        SpriteVertex* vertex_mapping;
        uint32_t* index_mapping;

    public:
        SpriteBuffer(const std::shared_ptr<VulkanDeviceContext>& context, uint32_t max_index_count = 200000);
        ~SpriteBuffer();
        void bind(VkCommandBuffer commandBuffer);
        void draw(VkCommandBuffer commandBuffer);
        
        void begin();
        bool append(const SpriteQuad& sprite);
        void flush();

    private:
        void create();
    };
}
